<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="pUnPN" id="pUnPN"><span data-lake-id="ufe09c534" id="ufe09c534">典型回答</span></h1>
  <p data-lake-id="ua8d94117" id="ua8d94117"><span data-lake-id="u66fabc10" id="u66fabc10">​</span><br></p>
  <p data-lake-id="uce602814" id="uce602814"><span data-lake-id="ub06103cd" id="ub06103cd">在Java中有两类线程：User Thread(用户线程)、Daemon Thread(守护线程) 。用户线程一般用于执行用户级任务，而守护线程也就是“后台线程”，一般用来执行后台任务，守护线程最典型的应用就是GC(垃圾回收器)。</span></p>
  <p data-lake-id="u0d685796" id="u0d685796"><span data-lake-id="u93a54a72" id="u93a54a72">​</span><br></p>
  <p data-lake-id="u8a3e5319" id="u8a3e5319"><span data-lake-id="u89d9371a" id="u89d9371a">这两种线程其实是没有什么区别的，唯一的区别就是Java虚拟机在所有&lt;用户线程&gt;都结束后就会退出，而不会等&lt;守护线程&gt;执行完。</span></p>
  <p data-lake-id="u19379b7d" id="u19379b7d"><br></p>
  <h1 data-lake-id="fMiOr" id="fMiOr"><span data-lake-id="u4acfda56" id="u4acfda56">扩展知识</span></h1>
  <p data-lake-id="ude7f3733" id="ude7f3733"><span data-lake-id="u53c2dfad" id="u53c2dfad">​</span><br></p>
  <h2 data-lake-id="JGP1I" id="JGP1I"><span data-lake-id="ube09e5cc" id="ube09e5cc">创建守护线程</span></h2>
  <p data-lake-id="u534432de" id="u534432de"><br></p>
  <p data-lake-id="u1ec5d9d1" id="u1ec5d9d1"><span data-lake-id="u2786b24f" id="u2786b24f">我们可以通过使用setDaemon()方法通过传递true作为参数，使线程成为一个守护线程。我们必须在启动线程之前调用一个线程的setDaemon()方法。否则，就会抛出一个java.lang.IllegalThreadStateException。</span></p>
  <p data-lake-id="u38825e38" id="u38825e38"><span data-lake-id="ufc6efbc6" id="ufc6efbc6">可以使用isDaemon()方法来检查线程是否是守护线程。</span></p>
  <pre lang="java"><code>
/**
* @author Hollis
*/
public class Main {
  public static void main(String[] args) {
    Thread t1 = new Thread();
    System.out.println(t1.isDaemon());
    t1.setDaemon(true);
    System.out.println(t1.isDaemon());
    t1.start();
    t1.setDaemon(false);
  }
}
</code></pre>
  <p data-lake-id="u0db08d98" id="u0db08d98"><span data-lake-id="u4f109083" id="u4f109083">以上代码输出结果：</span></p>
  <pre lang="java"><code>
false
true
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.setDaemon(Thread.java:1359)
at com.hollis.Main.main(Main.java:16)
</code></pre>
  <p data-lake-id="u944960f1" id="u944960f1"><span data-lake-id="u9e03d944" id="u9e03d944">我们提到，当JVM中只剩下守护线程的时候，JVM就会退出，那么写一段代码测试下：</span></p>
  <pre lang="java"><code>
/**
* @author Hollis
*/
public class Main {
  public static void main(String[] args) {
    Thread childThread = new Thread(new Runnable() {
      @Override
      public void run() {
        while (true) {
          System.out.println("I'm child thread..");
            try {
              TimeUnit.MILLISECONDS.sleep(1000);
            } catch (InterruptedException e) {
           	 e.printStackTrace();
            }
          }
        }
      });
    childThread.start();
    System.out.println("I'm main thread...");
  }
}
</code></pre>
  <p data-lake-id="u6363114b" id="u6363114b"><span data-lake-id="u10552381" id="u10552381">以上代码中，我们在Main线程中开启了一个子线程，在并没有显示将其设置为守护线程的情况下，他是一个用户线程，代码比较好理解，就是子线程处于一个while(true)循环中，每隔一秒打印一次I'm child thread..</span></p>
  <p data-lake-id="uffd6e6b5" id="uffd6e6b5"><span data-lake-id="u13dda325" id="u13dda325">输出结果为：</span></p>
  <pre lang="java"><code>
I'm main thread...
I'm child thread..
I'm child thread..
.....
I'm child thread..
I'm child thread..
</code></pre>
  <p data-lake-id="u4b03c921" id="u4b03c921"><span data-lake-id="u2c1dc35f" id="u2c1dc35f">我们再把子线程设置成守护线程，重新运行以上代码。</span></p>
  <pre lang="java"><code>
/**
* @author Hollis
*/
public class Main {
    public static void main(String[] args) {
    Thread childThread = new Thread(new Runnable() {
      @Override
      public void run() {
        while (true) {
        	System.out.println("I'm child thread..");
          try {
        	  TimeUnit.MILLISECONDS.sleep(1000);
          } catch (InterruptedException e) {
         	 e.printStackTrace();
          }
        }
      }
    });
    childThread.setDaemon(true);
    childThread.start();
    System.out.println("I'm main thread...");
  }
}
</code></pre>
  <p data-lake-id="u05c8a736" id="u05c8a736"><span data-lake-id="u5da7e3c7" id="u5da7e3c7">以上代码，我们通过childThread.setDaemon(true);把子线程设置成守护线程，然后运行，得到以下结果：</span></p>
  <pre lang="java"><code>
I'm main thread...
I'm child thread..
</code></pre>
  <p data-lake-id="u7ea10d79" id="u7ea10d79"><span data-lake-id="ub41496e4" id="ub41496e4">​</span><br></p>
  <p data-lake-id="u8c5ef468" id="u8c5ef468"><span data-lake-id="u549df165" id="u549df165">子线程只打印了一次，也就是，在main线程执行结束后，由于子线程是一个守护线程，JVM就会直接退出了。</span></p>
  <p data-lake-id="u55a60c01" id="u55a60c01"><span data-lake-id="uc671e22e" id="uc671e22e">值得注意的是，在Daemon线程中产生的新线程也是Daemon的。</span></p>
  <p data-lake-id="uf7fbac11" id="uf7fbac11"><br></p>
 </body>
</html>